/*
  Universidade Federal da Campina Grande
  Centro de Engenharia Elétrica e Informática
  Departamento de Sistemas e Computação
  Graduação em Ciência da Computação

  Disciplina: Compiladores
  Professor: Franklin Ramalho
  Aluno: Armstrong Mardilson da Silva Goes
*/

package javacompiler.lex;

import java_cup.runtime.*;
import javacompiler.syntax.sym;
import javacompiler.syntax.JavaSymbolInfo;
import javacompiler.syntax.IdGenerator;
import javacompiler.syntax.SymbolsTable;
import javacompiler.util.*;

%%

%class JavaLexicalAnalyser
%public
%column
%line
%cup

%{
	StringBuffer string = new StringBuffer();
	IdGenerator generator = IdGenerator.getInstance(); 
	SymbolsTable table = SymbolsTable.getInstance();
	Logger logger = new Logger();	

	private Symbol symbol(int type) {
		return new JavaSymbol(type, yyline, yycolumn);
	}
	
	private Symbol symbol(int type, Object val) {
		return new JavaSymbol(type, val, yyline, yycolumn);
	}

	private Symbol symbol(int type, String val) {
		return new JavaSymbol(type, yyline, yycolumn, val);
	}
%}

/*
   Definições básicas
*/
LineTerminator = \r|\n|\r\n
WhiteSpace = {LineTerminator} | [ \t\f]
DecimalDigits = [0-9][0-9]* 

/* Copiado do manual do JFlex */
Text = ( [^*] | \*+ [^/*] )*

//%state IDENTIFIER

%% 


{WhiteSpace} { /* Ignora */}
"/**"{Text}"*/" { /* Ignora */ }

/* palavras-chave */
"package" { return symbol(sym._package); }
"import" { return symbol(sym._import); }
"interface" { return symbol(sym._interface); }
"extends" { return symbol(sym._extends); }
"break" { return symbol(sym._break); }
"new" { return symbol(sym._new); }
"if" { return symbol(sym._if); }
"else" { return symbol(sym._else); }
"do" { return symbol(sym._do); }
"while" { return symbol(sym._while); }
"for" { return symbol(sym._for); }
"try" { return symbol(sym._try);}
"catch" { return symbol(sym._catch); }
"finally" { return symbol(sym._finally); }
"switch" { return symbol(sym._switch); }
"case" { return symbol(sym._case); }
"default" { return symbol(sym._default); }
"throw" { return symbol(sym._throw); }
"return" { return symbol(sym._return); }
"continue" { return symbol(sym._continue); }
"class" { return symbol(sym._class); }
"implements" { return symbol(sym._implements); }

/* Modificadores */
"public" { return symbol(sym._public); }
"private" { return symbol(sym._private); }
"protected" { return symbol(sym._protected); }
"static" { return symbol(sym._static); }
"final" { return symbol(sym._final); }
"native" { return symbol(sym._native); }
"synchronized" { return symbol(sym._synchronized); }
"abstract" { return symbol(sym._abstract); }
"threadsafe" { return symbol(sym._threadsafe); }
"transient" { return symbol(sym._transient); }

/* Operadores */
"=" { return symbol(sym.equals); }
"+" { return symbol(sym.plus); }
"+=" { return symbol(sym.plus_equals); } 
"-" { return symbol(sym.minus); }
"-=" { return symbol(sym.minus_equals); }
"*" { return symbol(sym.times); }
"*=" { return symbol(sym.times_equals); }
"/" { return symbol(sym.div); }
"/=" { return symbol(sym.div_equals); }
"%" { return symbol(sym.mod); }
"%=" { return symbol(sym.mod_equals); }
"++" { return symbol(sym.plusplus);} 
"--" { return symbol(sym.minusminus); }
">" { return symbol(sym.greater); }
"<" { return symbol(sym.less); }
">=" { return symbol(sym.greater_equal); }
"<=" { return symbol(sym.less_equal); }
"==" { return symbol(sym.equal_to); }
"!=" { return symbol(sym.not_equal_to); }
"!" { return symbol(sym.not); }
"&" { return symbol(sym.ampersand); }
"&=" { return symbol(sym.ampersand_equals); }
"|" { return symbol(sym.bit_or); }
"|=" { return symbol(sym.bit_or_equals); }
"^" { return symbol(sym.circ); }
"^=" { return symbol(sym.circ_and_equals); }
"&&" { return symbol(sym.amperamper); }
"||=" { return symbol(sym.or_equals); }
"?" { return symbol(sym.interr); }
":" { return symbol(sym.colon); }
"~" { return symbol(sym.til); }
">>=" { return symbol(sym.shift_right_equals); }
"<<" { return symbol(sym.shift_left); }
">>" { return symbol(sym.shift_right); }
">>>" { return symbol(sym.right_rotation); }
"instanceof" { return symbol(sym._instanceof); }

/* Valores */
"true"
{ 
	JavaSymbolInfo info = new JavaSymbolInfo();
	info.setType(JavaSymbolInfo.LexType.Bool);
	info.setLine(yyline);	
        info.setColumn(yycolumn);
	long id = generator.generate();
	table.addSymbol(id, info);
	return symbol(sym._true, id); 
}

"false" 
{
	JavaSymbolInfo info = new JavaSymbolInfo();
	info.setType(JavaSymbolInfo.LexType.Bool);
	info.setLine(yyline);
        info.setColumn(yycolumn);
	long id = generator.generate();
	table.addSymbol(id, info);
	return symbol(sym._false, id);
}

"null" { return symbol(sym._null); }
"super" { return symbol(sym._super); }
"this" { return symbol(sym._this); }

/* Tipos */
"boolean"  { return symbol(sym._boolean); }
"byte" { return symbol(sym._byte); }
"char" { return symbol(sym._char); }
"short" { return symbol(sym._short); }
"int" { return symbol(sym._int); }
"float"   { return symbol(sym._float); }
"long" { return symbol(sym._long); }
"double" { return symbol(sym._double); }
"void" { return symbol(sym._void); }

/* Outros símbolos */
"." { return symbol(sym.dot); }
";" { return symbol(sym.semicolon); }
"," { return symbol(sym.comma); }
"*" { return symbol(sym.ast); }
"{" { return symbol(sym.open_brackets); }
"}" { return symbol(sym.close_brackets); }
"[" { return symbol(sym.open_square_bracket); }
"]" { return symbol(sym.close_square_bracket); }
"(" { return symbol(sym.open_parenthesis); }
")" { return symbol(sym.close_parenthesis); }

[_$a-zA-z][_$a-zA-z0-9]* 
{
	 JavaSymbolInfo info = new JavaSymbolInfo();
	 info.setType(JavaSymbolInfo.LexType.Identifier);
	 logger.debug("identifier: " + yytext());
	 info.setIdValue(yytext());
	 info.setLine(yyline);
	 info.setColumn(yycolumn);
	 long id = generator.generate();
	 table.addIdentifier(id, info);
	 return symbol(sym.identifier, id); 
}

[1-9][0-9]*[L]? 
{ 
	JavaSymbolInfo info = new JavaSymbolInfo();
	info.setType(JavaSymbolInfo.LexType.Int);
	info.setIntValue(Integer.parseInt(yytext()));
	info.setLine(yyline);
        info.setColumn(yycolumn);
	long id = generator.generate();
	table.addSymbol(id, info);
	return symbol(sym.integer, id); 
}

0x[0-9a-f]+ 	
{
	JavaSymbolInfo info = new JavaSymbolInfo();
	info.setType(JavaSymbolInfo.LexType.Int);
	info.setIntValue(Integer.parseInt(yytext()));
	info.setLine(yyline);
        info.setColumn(yycolumn);
	long id = generator.generate();
	table.addSymbol(id, info);
	return symbol(sym.integer, id); 
}

0 		
{
	JavaSymbolInfo info = new JavaSymbolInfo();
	info.setType(JavaSymbolInfo.LexType.Int);
	info.setLine(yyline);
        info.setColumn(yycolumn);
	long id = generator.generate();
	table.addSymbol(id, info);
	return symbol(sym.integer, id); 
}

{DecimalDigits}"."{DecimalDigits} 
{
	JavaSymbolInfo info = new JavaSymbolInfo();
	info.setType(JavaSymbolInfo.LexType.Float);
        info.setDoubleValue(Double.parseDouble(yytext()));
	info.setLine(yyline);
        info.setColumn(yycolumn);
	logger.debug("Float: " + yytext());
	long id = generator.generate();
	table.addSymbol(id, info);
	return symbol(sym.floating, id); 
}

"\""{Text}"\"" 
{ 
	JavaSymbolInfo info = new JavaSymbolInfo();
	info.setType(JavaSymbolInfo.LexType.String);
	info.setLine(yyline);
        info.setColumn(yycolumn);
	long id = generator.generate();
	table.addSymbol(id, info);
	return symbol(sym.string, id); 
}


